function GetAvgX(L: TList): extended;
var
  minx, maxx, x: extended;
  z: integer;
begin
  minx := 66666;
  maxx := -66666;
  for z := 0 to L.Count - 1 do
  begin
    if assigned(L.Items[z]) then
      if TObject(L.Items[z]) is TGPoint then
      begin
        x := TGPoint(L.Items[z]).getX;
        if x > maxx then
          maxx := x;
        if x < minx then
          minx := x;
      end;
  end;
  result := (maxx + minx) / 2;
end;

// ---------------------------------------------------------------------

function Next(i: integer; L: TList): integer;
begin
  inc(i);
  if i = L.Count then
    i := 0;
  result := i;
end;

function prev(i: integer; L: TList): integer;
begin
  dec(i);
  if i < 0 then
    i := L.Count - 1;
  result := i;
end;

// ---------------------------------------------------------------------
procedure GetVPoly(i: integer; var L: TList);
var
  z: integer;
begin
  if assigned(L) then
  begin
    L.Clear;
  end
  else
    L := TList.Create;
  for z := 0 to ListPoints.Count - 1 do
    if assigned(ListPoints.Items[z]) then
      if TObject(ListPoints.Items[z]) is TGLine then
        if (TGLine(ListPoints.Items[z]).BisectorOf[1] = i) or
          (TGLine(ListPoints.Items[z]).BisectorOf[2] = i) then
          TGLine(ListPoints.Items[z]).CopyToList(L);
end;


// ---------------------------------------------------------------------

function FindMinIPDistance(var slist: TList; var sindex: integer;
  var ip: TGPoint): extended;
var
  z: integer;
  p: TGPoint;
  min: extended;
begin
  p := nil;
  ip := nil;
  min := 66666;
  for z := 0 to slist.Count - 1 do
    if TGLine(slist.Items[z]).Intersect(Edge) then
    begin
      TGLine(slist.Items[z]).GetCurrentIPoint(p);
      if (v.DistanceTo(p) < min) and (v.DistanceTo(p) > 1E-5) then
      begin // must be with security distance
        min := v.DistanceTo(p);
        ip := p.clone as TGPoint;
        sindex := z;
      end;
    end;
  p.Free;
  result := min;
end;


// ---------------------------------------------------------------------

function SortY(i1, i2: pointer): integer;
begin
  if TGPoint(i1).getY > TGPoint(i2).getY then
    result := 1
  else
    result := -1;
end;

function SortX(i1, i2: pointer): integer;
begin
  if TGPoint(i1).getX > TGPoint(i2).getX then
    result := 1
  else
    result := -1;
end;

procedure sort(L: TList; cf: TListSortCompare);
// performs a bubble sort. TList.sort doesn't work for some reason.
var
  z, i: integer;
  p: pointer;
begin
  for z := L.Count - 2 downto 0 do
    for i := 0 to z do
    begin
      if cf(L.Items[i], L.Items[i + 1]) < 0 then
      begin
        p := L.Items[i];
        L.Items[i] := L.Items[i + 1];
        L.Items[i + 1] := p; // exchange items
        TGraphObject(L.Items[i]).ReIndex(false, i);
        TGraphObject(L.Items[i + 1]).ReIndex(false, i + 1);
      end;
    end;

end;

// ---------------------------------------------------------------------

procedure DiscardLines;
var
  a, b, c: integer;
  ip: TGPoint;
  l1, l2: TGLine;
label Next;
begin
  l2 := nil;
  a := 0;
  while a < ListPoints.Count do
  begin
    if TObject(ListPoints.Items[a]) is TGLine then
    begin
      l1 := ListPoints.Items[a];

      for b := 0 to ConvexHull1.Count - 1 do
        if (l1.BisectorOf[1] = TGPoint(ConvexHull1.Items[b]).getOrigIndex) or
          (l1.BisectorOf[2] = TGPoint(ConvexHull1.Items[b]).getOrigIndex) then
        begin // l1 should be left from chain
          if l2 <> nil then
          begin
            l2.p2.Free;
            l2.Free;
          end;
          l2 := TGLine.Create(l1.p1, TGPoint.Create(l1.p1.getX - 1, l1.p1.getY,
            nil, nil), OnePoint, nil, nil);
          for c := 0 to chain.Count - 1 do
          begin
            if l2.Intersect(chain.Items[c]) then
            begin
              ip := nil;
              l2.GetCurrentIPoint(ip);
              if l1.p1.DistanceTo(ip) > 1E-5 then
              begin
                ip.Free;
                TGLine(ListPoints.Items[a]).Delete(true);
                dec(a);
                goto Next;
              end;
            end;
          end;
        end;

      for b := 0 to ConvexHull2.Count - 1 do
        if (l1.BisectorOf[1] = TGPoint(ConvexHull2.Items[b]).getOrigIndex) or
          (l1.BisectorOf[2] = TGPoint(ConvexHull2.Items[b]).getOrigIndex) then
        begin // l1 should be right from chain
          if l2 <> nil then
          begin
            l2.p2.Free;
            l2.Free;
          end;
          l2 := TGLine.Create(l1.p1, TGPoint.Create(l1.p1.getX + 1, l1.p1.getY,
            nil, nil), OnePoint, nil, nil);
          for c := 0 to chain.Count - 1 do
          begin
            if l2.Intersect(chain.Items[c]) then
            begin
              ip := nil;
              l2.GetCurrentIPoint(ip);
              if l1.p1.DistanceTo(ip) > 1E-5 then
              begin
                ip.Free;
                TGLine(ListPoints.Items[a]).Delete(true);
                dec(a);
                goto Next;
              end;
            end;
          end;
        end;
    Next:
    end;
    inc(a);
  end; // while
end;
